<script setup lang='ts'>
import { computed, onUnmounted, ref } from 'vue'
import { NDropdown } from 'naive-ui'
import AvatarComponent from './Avatar.vue'
import TextComponent from './Text.vue'
import { SvgIcon } from '@/components/common'
import { copyText } from '@/utils/format'
import { useIconRender } from '@/hooks/useIconRender'
import { useBasicLayout } from '@/hooks/useBasicLayout'
import { t } from '@/locales'

interface Props {
	dateTime?: string
	text?: string
	inversion?: boolean
	error?: boolean
	loading?: boolean
}

interface Emit {
	(ev: 'regenerate'): void
	(ev: 'delete'): void
}

const props = defineProps<Props>()

const emit = defineEmits<Emit>()

const { isMobile } = useBasicLayout()

const { iconRender } = useIconRender()

const textRef = ref<HTMLElement>()
const asRawText = ref(props.inversion)
const messageRef = ref<HTMLElement>()
const abortController = new AbortController()

const options = computed(() => {
	const common = [
		{
			label: t('chat.copy'),
			key: 'copyText',
			icon: iconRender({ icon: 'ri:file-copy-2-line' }),
		},
		{
			label: t('common.delete'),
			key: 'delete',
			icon: iconRender({ icon: 'ri:delete-bin-line' }),
		},
	]

	if (!props.inversion) {
		common.unshift({
			label: asRawText.value ? t('chat.preview') : t('chat.showRawText'),
			key: 'toggleRenderType',
			icon: iconRender({ icon: asRawText.value ? 'ic:outline-code-off' : 'ic:outline-code' }),
		})
	}

	return common
})

async function handleSelect(key: 'copyText' | 'delete' | 'toggleRenderType') {
	switch (key) {
		case 'copyText':
			copyText({ text: props.text ?? '' })
			return
		case 'toggleRenderType':
			asRawText.value = !asRawText.value
			return
		case 'delete':
			emit('delete')
			break
		default:
			break
	}
}

function handleRegenerate() {
	messageRef.value?.scrollIntoView()
	emit('regenerate')
}

onUnmounted(() => {
	abortController?.abort()
})
</script>

<template>
	<div ref="messageRef" class="flex w-full mb-6 overflow-hidden" :class="[{ 'flex-row-reverse': inversion }]">
		<div class="flex items-center justify-center flex-shrink-0 h-8 overflow-hidden rounded-full basis-8"
			:class="[inversion ? 'ml-2' : 'mr-2']">
			<AvatarComponent :image="inversion" />
		</div>
		<div class="overflow-hidden text-sm " :class="[inversion ? 'items-end' : 'items-start']">
			<p class="text-xs text-[#b4bbc4]" :class="[inversion ? 'text-right' : 'text-left']">
				{{ dateTime }}
			</p>
			<div class="flex items-end gap-1 mt-2" :class="[inversion ? 'flex-row-reverse' : 'flex-row']">
				<TextComponent ref="textRef" :inversion="inversion" :error="error" :text="text" :loading="loading"
					:as-raw-text="asRawText" />
				<div class="flex flex-col">
					<button v-if="!inversion"
						class="mb-2 transition text-neutral-300 hover:text-neutral-800 dark:hover:text-neutral-300"
						@click="handleRegenerate">
						<SvgIcon icon="ri:restart-line" />
					</button>
					<NDropdown :trigger="isMobile ? 'click' : 'hover'" :placement="!inversion ? 'right' : 'left'" :options="options"
						@select="handleSelect">
						<button class="transition text-neutral-300 hover:text-neutral-800 dark:hover:text-neutral-200">
							<SvgIcon icon="ri:more-2-fill" />
						</button>
					</NDropdown>
				</div>
			</div>
		</div>
	</div>
</template>
